home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / Managed / Direct3D / PrtPerVertex / PrtPerVertex.cs < prev    next >
Encoding:
Text File  |  2004-09-27  |  86.3 KB  |  1,819 lines

  1. //-----------------------------------------------------------------------------
  2. // File: PrtPerVertex.cs
  3. //
  4. // This sample demonstrates how use D3DXSHPrtSimulation(), a per vertex  
  5. // precomputed radiance transfer (Prt) simulator that uses low-order 
  6. // spherical harmonics (SH) and records the results to a file. The sample 
  7. // then demonstrates how compress the results with clustered principal 
  8. // component analysis (CPca) and view the compressed results with arbitrary 
  9. // lighting in real time with a vs_1_1 vertex shader
  10. //
  11. // Copyright (c) Microsoft Corporation. All rights reserved.
  12. //-----------------------------------------------------------------------------
  13.  
  14. // Enable extra D3D debugging in debug builds.  This makes D3D objects work well
  15. // in the debugger watch window, but slows down performance slightly.
  16. #if (DEBUG || _DEBUG)
  17. #define D3D_DEBUG_INFO
  18. #endif
  19.  
  20. //#define DEBUG_VS   // Uncomment this line to debug vertex shaders 
  21. //#define DEBUG_PS   // Uncomment this line to debug pixel shaders 
  22.  
  23. using System;
  24. using System.Text;
  25. using System.Text.RegularExpressions;
  26. using System.Drawing;
  27. using System.IO;
  28. using Microsoft.DirectX;
  29. using Microsoft.DirectX.Direct3D;
  30. using Microsoft.Samples.DirectX.UtilityToolkit;
  31.  
  32. namespace PrtPerVertexSample
  33. {
  34.     /// <summary>PrtPerVertex Sample Class</summary>
  35.     class PrtPerVertex : IFrameworkCallback, IDeviceCreation
  36.     {
  37.         #region Creation
  38.         /// <summary>Create a new instance of the class</summary>
  39.         public PrtPerVertex(Framework sampleFramework) 
  40.         { 
  41.             for( int i = 0; i < NumberSkyBoxes; i++)
  42.                 skybox[i] = new Skybox();
  43.  
  44.             for( int i = 0; i < NumberSkyBoxes; i++)
  45.                 for( int j = 0; j < 3; j++)
  46.                     skyboxLightSH[i, j] = new float[SphericalHarmonics.MaximumOrder * SphericalHarmonics.MaximumOrder];
  47.  
  48.             // Store framework
  49.             SampleFramework = sampleFramework;
  50.             // Create dialogs
  51.             hud = new Dialog(SampleFramework); 
  52.             startUpUI   = new Dialog(SampleFramework); 
  53.             startUpUI2  = new Dialog(SampleFramework);
  54.             simulatorRunningUI  = new Dialog(SampleFramework);
  55.             renderingUI = new Dialog(SampleFramework);
  56.             renderingUI2    = new Dialog(SampleFramework);
  57.             renderingUI3    = new Dialog(SampleFramework);
  58.             compressionUI   = new Dialog(SampleFramework);
  59.         }
  60.         #endregion
  61.  
  62.         #region Instance Data
  63.         // Variables
  64.         public static Framework SampleFramework = null; // Framework for samples
  65.         private Microsoft.DirectX.Direct3D.Font statsFont = null; // Font for drawing text
  66.         private Sprite textSprite = null; // Sprite for batching text calls
  67.         private ModelViewerCamera camera = new ModelViewerCamera(); // A model viewing camera
  68.         private bool isHelpShowing = true; // If true, renders the UI help text
  69.  
  70.         private Dialog hud = null; // dialog for standard controls
  71.         private Dialog startUpUI = null; // dialog for startup
  72.         private Dialog startUpUI2 = null; // dialog for startup
  73.         private Dialog simulatorRunningUI = null; // dialog for while simulator running
  74.         private Dialog renderingUI = null; // dialog for while Prt rendering 
  75.         private Dialog renderingUI2 = null; // dialog for while Prt rendering 
  76.         private Dialog renderingUI3 = null; // dialog for while Prt rendering 
  77.         private Dialog compressionUI = null; // dialog for Prt compression settings
  78.  
  79.         private PrtMesh prtMesh = new PrtMesh();
  80.  
  81.         private bool IsRenderEnvMap = true;
  82.         private bool IsRenderUI = true;
  83.         private bool IsRenderArrows = true;
  84.         private bool IsRenderMesh = true;
  85.         private bool IsRenderText = true;
  86.         private bool IsRenderWithAlbedoTexture = true;
  87.         private bool IsRenderCompressionUI = false;
  88.         private bool IsWireframe = false;
  89.         private bool IsRenderSHProjection = false;
  90.  
  91.         private float currentObjectRadius = -1.0f;
  92.         private int technique = 0;
  93.         private float lightScaleForPrt     = 0.0f;
  94.         private float lightScaleForSHIrrad = 0.0f;
  95.         private float lightScaleForNDotL   = 1.0f;
  96.  
  97.         private const int NumberSkyBoxes = 5;
  98.         private Skybox[] skybox = new Skybox[NumberSkyBoxes];
  99.         private float[,][] skyboxLightSH = new float[NumberSkyBoxes, 3][];
  100.         private int skyboxA = 0;
  101.         private int skyboxB = 1;
  102.  
  103.         public const int MaximumLights = 10;
  104.         private DirectionWidget[] lightControl = new DirectionWidget[MaximumLights];
  105.         private int numberActiveLights;
  106.         private int activeLight;
  107.  
  108.         private SHCubeProj projData = new SHCubeProj();
  109.  
  110.         private enum ApplicationState
  111.         {
  112.             Startup,
  113.             SimulatorOptions,
  114.             SimulatorRunning,
  115.             LoadPrtBuffer,
  116.             RenderScene
  117.         };
  118.  
  119.         private ApplicationState applicationState = ApplicationState.Startup; // State of the application
  120.         #endregion
  121.  
  122.         #region Static Data
  123.         public static PrtSimulator Simulator = new PrtSimulator();
  124.         #endregion
  125.  
  126.         #region Global Constants
  127.         public static readonly ColorValue White = ColorValue.FromColor(Color.White);
  128.         public static readonly ColorValue Yellow = ColorValue.FromColor(Color.Yellow);
  129.         public static readonly Color ClearColor1 = Color.FromArgb(0, 45, 50, 170);
  130.         #endregion
  131.  
  132.         #region UI Control Constants
  133.         // HUD Ui Control constants
  134.         private const int Static = 0;
  135.         private const int ToggleFullscreen = 1;
  136.         private const int ToggleReference = 3;
  137.         private const int ChangeDevice = 4;
  138.  
  139.         private const int NumberLights = 6;
  140.         private const int NumberLightsStatic = 7;
  141.         private const int ActiveLight = 8;
  142.         private const int LightScale = 9;
  143.         private const int LightScaleStatic = 10;
  144.  
  145.         private const int LoadPrtBuffer = 12;
  146.         private const int SimulatorInt32 = 13;
  147.         private const int StopSimulator = 14;
  148.  
  149.         private const int EnvironmentOne = 15;
  150.         private const int EnvironmentTwo = 16;
  151.         private const int Directional = 17;
  152.         private const int EnvironmentBlend = 18;
  153.         private const int EnvironmentA = 19;
  154.         private const int EnvironmentB = 20;
  155.  
  156.         private const int RenderUI = 21;
  157.         private const int RenderMap = 22;
  158.         private const int RenderArrows = 23;
  159.         private const int RenderMesh = 24;
  160.         private const int SimulatorStatus = 25;
  161.         private const int SimulatorStatus2 = 26;
  162.  
  163.         private const int NumberPcaVectors = 27;
  164.         private const int NumberClusters = 29;
  165.         private const int MaximumConstants = 31;
  166.         private const int CurrentConstants = 32;
  167.         private const int CurrentConstantsStatic = 34;
  168.  
  169.         private const int Apply = 33;
  170.         private const int LightAngleStatic = 35;
  171.         private const int LightAngle = 36;
  172.         private const int RenderTexture = 37;
  173.         private const int WireFrame = 38;
  174.         private const int Restart = 40;
  175.         private const int Compression = 41;
  176.         private const int SHProjection = 42;
  177.  
  178.         private const int TechniquePrt = 43;
  179.         private const int TechniqueSHIrrad = 44;
  180.         private const int TechniqueNDotL = 45;
  181.  
  182.         private const int Scene1 = 46;
  183.         private const int Scene2 = 47;
  184.         private const int Scene3 = 48;
  185.         private const int Scene4 = 49;
  186.         private const int Scene5 = 50;
  187.  
  188.         #endregion
  189.  
  190.         private struct SHCubeProj 
  191.         {
  192.             public float[] Red, Green, Blue;
  193.             public int OrderUse; // order to use
  194.             public float[] ConvolutionCoefficients; // convolution coefficients
  195.  
  196.             public void InitDiffCubeMap(float[] R, float[] G, float[] B)
  197.             {
  198.                 Red = R;
  199.                 Green = G;
  200.                 Blue = B;
  201.  
  202.                 OrderUse = 3; // go to 5 is a bit more accurate...
  203.  
  204.                 ConvolutionCoefficients = new float[6];
  205.                 ConvolutionCoefficients[0] = 1.0f;
  206.                 ConvolutionCoefficients[1] = 2.0f/3.0f;
  207.                 ConvolutionCoefficients[2] = 1.0f/4.0f;
  208.                 ConvolutionCoefficients[3] = ConvolutionCoefficients[5] = 0.0f;
  209.                 ConvolutionCoefficients[4] = -6.0f/144.0f;
  210.             }
  211.  
  212.             public void Init(float[] R, float[] G, float[] B)
  213.             {
  214.                 Red = R;
  215.                 Green = G;
  216.                 Blue = B;
  217.  
  218.                 OrderUse = 6;
  219.  
  220.                 ConvolutionCoefficients = new float[6];
  221.                 for(int i = 0; i < 6; i++)
  222.                     ConvolutionCoefficients[i] = 1.0f;
  223.             }
  224.         };
  225.  
  226.         private Vector4 SHCubeFill(Vector3 texCoord, Vector3 texelSize)
  227.         {
  228.             texCoord.Normalize();
  229.             float[] vals = new float[36];
  230.             SphericalHarmonics.EvaluateDirection(vals, projData.OrderUse, texCoord);
  231.  
  232.             Vector4 outVector = Vector4.Empty; // just clear it out...
  233.  
  234.             int l, m, index = 0;
  235.             for(l = 0; l < projData.OrderUse; l++) 
  236.             {
  237.                 float ConvUse = projData.ConvolutionCoefficients[l];
  238.                 for(m = 0; m < 2 * l + 1; m++) 
  239.                 {
  240.                     outVector.X += ConvUse * vals[index] * projData.Red[index];
  241.                     outVector.Y += ConvUse * vals[index] * projData.Green[index];
  242.                     outVector.Z += ConvUse * vals[index] * projData.Blue[index];
  243.                     outVector.W = 1;
  244.  
  245.                     index++;
  246.                 }
  247.             }
  248.  
  249.             return outVector;
  250.         }
  251.  
  252.  
  253.         /// <summary>
  254.         /// Called during device initialization, this code checks the device for some 
  255.         /// minimum set of capabilities, and rejects those that don't pass by returning false.
  256.         /// </summary>
  257.         public bool IsDeviceAcceptable(Caps caps, Format adapterFormat, Format backBufferFormat, bool windowed)
  258.         {
  259.             // Skip back buffer formats that don't support alpha blending
  260.             if (!Manager.CheckDeviceFormat(caps.AdapterOrdinal, caps.DeviceType, adapterFormat, 
  261.                 Usage.QueryPostPixelShaderBlending, ResourceType.Textures, backBufferFormat))
  262.                 return false;
  263.  
  264.             return true;
  265.         }
  266.  
  267.         /// <summary>
  268.         /// This callback function is called immediately before a device is created to allow the 
  269.         /// application to modify the device settings. The supplied settings parameter 
  270.         /// contains the settings that the framework has selected for the new device, and the 
  271.         /// application can make any desired changes directly to this structure.  Note however that 
  272.         /// the sample framework will not correct invalid device settings so care must be taken 
  273.         /// to return valid device settings, otherwise creating the Device will fail.  
  274.         /// </summary>
  275.         public void ModifyDeviceSettings(DeviceSettings settings, Caps caps)
  276.         {
  277.             // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW 
  278.             // then switch to SWVP.
  279.             if ( (!caps.DeviceCaps.SupportsHardwareTransformAndLight) ||
  280.                 (caps.VertexShaderVersion < new Version(1,1)) )
  281.             {
  282.                 settings.BehaviorFlags = CreateFlags.SoftwareVertexProcessing;
  283.             }
  284.             else
  285.             {
  286.                 settings.BehaviorFlags = CreateFlags.HardwareVertexProcessing;
  287.             }
  288.  
  289.             // The PRT simulator runs on a seperate thread.  If you are just 
  290.             // loading simulator results, then this isn't needed
  291.             settings.BehaviorFlags |= CreateFlags.MultiThreaded;
  292.  
  293.             // This application is designed to work on a pure device by not using 
  294.             // any get methods, so create a pure device if supported and using HWVP.
  295.             if ( (caps.DeviceCaps.SupportsPureDevice) && 
  296.                 ((settings.BehaviorFlags & CreateFlags.HardwareVertexProcessing) != 0 ) )
  297.                 settings.BehaviorFlags |= CreateFlags.PureDevice;
  298.  
  299.             // Debugging vertex shaders requires either REF or software vertex processing 
  300.             // and debugging pixel shaders requires REF.  
  301. #if(DEBUG_VS)
  302.             if (settings.DeviceType != DeviceType.Reference )
  303.             {
  304.                 settings.BehaviorFlags &= ~CreateFlags.HardwareVertexProcessing;
  305.                 settings.BehaviorFlags &= ~CreateFlags.PureDevice;
  306.                 settings.BehaviorFlags |= CreateFlags.SoftwareVertexProcessing;
  307.             }
  308. #endif
  309. #if(DEBUG_PS)
  310.             settings.DeviceType = DeviceType.Reference;
  311. #endif
  312.         }
  313.  
  314.         /// <summary>
  315.         /// This event will be fired immediately after the Direct3D device has been 
  316.         /// created, which will happen during application initialization and windowed/full screen 
  317.         /// toggles. This is the best location to create Pool.Managed resources since these 
  318.         /// resources need to be reloaded whenever the device is destroyed. Resources created  
  319.         /// here should be released in the Disposing event. 
  320.         /// </summary>
  321.         private void OnCreateDevice(object sender, DeviceEventArgs e)
  322.         {
  323.             string cubeMapFileName;
  324.  
  325.             Device device = e.Device;
  326.  
  327.             for(int i = 0; i < NumberSkyBoxes; ++i )
  328.             {
  329.                 switch( i )
  330.                 {
  331.                     case 0: cubeMapFileName = "Light Probes\\rnl_cross.dds"; break;
  332.                     case 1: cubeMapFileName = "Light Probes\\uffizi_cross.dds"; break;
  333.                     case 2: cubeMapFileName = "Light Probes\\galileo_cross.dds"; break;
  334.                     case 3: cubeMapFileName = "Light Probes\\grace_cross.dds"; break;
  335.                     case 4: 
  336.                     default: cubeMapFileName = "Light Probes\\stpeters_cross.dds"; break;
  337.                 }
  338.  
  339.                 skybox[i].OnCreateDevice( device, 50, cubeMapFileName, "SkyBox.fx" );
  340.  
  341.                 SphericalHarmonics.ProjectCubeMap(6, skybox[i].EnvironmentMap, skyboxLightSH[i, 0], skyboxLightSH[i, 1], skyboxLightSH[i, 2] );
  342.  
  343.                 // now compute the SH projection of the skybox...
  344.                 CubeTextureRequirements ctr = new CubeTextureRequirements();
  345.                 ctr.Format = Format.A16B16G16R16F;
  346.                 TextureLoader.CheckCubeTextureRequirements(device, Usage.None, Pool.Managed, out ctr);
  347.                 CubeTexture shCubeTexture = new CubeTexture(device, 256, 1, Usage.None, ctr.Format, Pool.Managed);
  348.  
  349.                 projData.Init(skyboxLightSH[i,0], skyboxLightSH[i,1], skyboxLightSH[i,2]);
  350.                 TextureLoader.FillTexture(shCubeTexture, new Fill3DTextureCallback(SHCubeFill));
  351.                 skybox[i].InitSH(shCubeTexture);
  352.             }
  353.  
  354.             prtMesh.OnCreateDevice(device);
  355.  
  356.             // Initialize the font
  357.             statsFont = ResourceCache.GetGlobalInstance().CreateFont(e.Device, 15, 0, FontWeight.Bold, 0, false, CharacterSet.Default, Precision.Default, FontQuality.Default, PitchAndFamily.FamilyDoNotCare | PitchAndFamily.DefaultPitch, "Arial");
  358.             DirectionWidget.OnCreateDevice(device);
  359.  
  360.             // Setup the camera's view parameters
  361.             camera.SetViewParameters(new Vector3(0.0f, 0.0f, -5.0f), Vector3.Empty);
  362.  
  363.             int max = (SampleFramework.DeviceCaps.MaxVertexShaderConst - 4) / 2;
  364.             compressionUI.GetSlider( NumberClusters ).SetRange( 1, max );
  365.  
  366.             string str = string.Format("Max VS Constants: {0}", SampleFramework.DeviceCaps.MaxVertexShaderConst);
  367.             compressionUI.GetStaticText( MaximumConstants ).SetText( str );
  368.             UpdateConstText();
  369.         }
  370.         
  371.         /// <summary>
  372.         /// This event will be fired immediately after the Direct3D device has been 
  373.         /// reset, which will happen after a lost device scenario. This is the best location to 
  374.         /// create Pool.Default resources since these resources need to be reloaded whenever 
  375.         /// the device is lost. Resources created here should be released in the OnLostDevice 
  376.         /// event. 
  377.         /// </summary>
  378.         private void OnResetDevice(object sender, DeviceEventArgs e)
  379.         {
  380.             SurfaceDescription backBufferSurfaceDesc = e.BackBufferDescription;
  381.  
  382.             for(int i = 0; i < NumberSkyBoxes; ++i )
  383.                 skybox[i].OnResetDevice( backBufferSurfaceDesc ); 
  384.  
  385.             prtMesh.OnResetDevice();
  386.  
  387.             if(statsFont != null)
  388.                 statsFont.OnResetDevice();
  389.  
  390.             Device device = e.Device;
  391.  
  392.             // Create a sprite to help batch calls when drawing many lines of text
  393.             if(textSprite == null)
  394.                 textSprite = new Sprite(device);
  395.             else
  396.                 textSprite.OnResetDevice();
  397.  
  398.             for( int i = 0; i < MaximumLights; i++ )
  399.                 lightControl[i].OnResetDevice( backBufferSurfaceDesc );
  400.  
  401.             // Setup the camera's projection parameters
  402.             float aspectRatio = (float)backBufferSurfaceDesc.Width / (float)backBufferSurfaceDesc.Height;
  403.             camera.SetProjectionParameters((float)Math.PI / 4, aspectRatio, 1.0f, 10000.0f);
  404.             camera.SetWindow(backBufferSurfaceDesc.Width, backBufferSurfaceDesc.Height);
  405.             camera.SetButtonMasks((int) MouseButtonMask.Left, (int) MouseButtonMask.Wheel, (int) MouseButtonMask.Right);
  406.             camera.IsAttachedToModel = true;
  407.  
  408.             if( prtMesh.Mesh != null )
  409.             {
  410.                 SetRadii();
  411.             }
  412.  
  413.             // Setup UI locations
  414.             hud.SetLocation(backBufferSurfaceDesc.Width - 170, 0);
  415.             hud.SetSize(170, 100);
  416.  
  417.             startUpUI.SetLocation( (backBufferSurfaceDesc.Width - 300) / 2, (backBufferSurfaceDesc.Height - 200) / 2 );
  418.             startUpUI.SetSize( 300, 200 );
  419.  
  420.             startUpUI2.SetLocation( 50, (backBufferSurfaceDesc.Height - 200) );
  421.             startUpUI2.SetSize( 300, 200 );
  422.  
  423.             compressionUI.SetLocation( 0, 150 );
  424.             compressionUI.SetSize( 200, 200 );
  425.  
  426.             simulatorRunningUI.SetLocation( (backBufferSurfaceDesc.Width - 600) / 2, (backBufferSurfaceDesc.Height - 100) / 2 );
  427.             simulatorRunningUI.SetSize( 600, 100 );
  428.  
  429.             renderingUI.SetLocation( 0, backBufferSurfaceDesc.Height - 125 );
  430.             renderingUI.SetSize( backBufferSurfaceDesc.Width, 125 );
  431.  
  432.             renderingUI2.SetLocation( backBufferSurfaceDesc.Width - 170, 100 );
  433.             renderingUI2.SetSize( 170, 400 );
  434.  
  435.             renderingUI3.SetLocation( 10, 30 );
  436.             renderingUI3.SetSize( 200, 100 );
  437.         }
  438.  
  439.         private void SetRadii()
  440.         {
  441.             // Update camera's viewing radius based on the object radius
  442.             float objectRadius = prtMesh.Radius;
  443.             if( currentObjectRadius != objectRadius )
  444.             {
  445.                 currentObjectRadius = objectRadius;
  446.                 camera.SetRadius( objectRadius * 3.0f, objectRadius * 0.1f, objectRadius * 20.0f );
  447.             }
  448.             camera.SetModelCenter( prtMesh.Center );
  449.             for( int i = 0; i < MaximumLights; i++ )
  450.                 lightControl[i].Radius = objectRadius;
  451.         }
  452.  
  453.         /// <summary>
  454.         /// This event function will be called fired after the Direct3D device has 
  455.         /// entered a lost state and before Device.Reset() is called. Resources created
  456.         /// in the OnResetDevice callback should be released here, which generally includes all 
  457.         /// Pool.Default resources. See the "Lost Devices" section of the documentation for 
  458.         /// information about lost devices.
  459.         /// </summary>
  460.         private void OnLostDevice(object sender, EventArgs e)
  461.         {
  462.             if(skybox != null)
  463.                 for(int i = 0; i < NumberSkyBoxes; ++i )
  464.                 {
  465.                     if(skybox[i] != null)
  466.                         skybox[i].OnLostDevice();
  467.                 }
  468.  
  469.             DirectionWidget.OnLostDevice();
  470.  
  471.             if (textSprite != null)
  472.             {
  473.                 textSprite.Dispose();
  474.                 textSprite = null;
  475.             }
  476.  
  477.             if( prtMesh != null)
  478.                 prtMesh.OnLostDevice();
  479.         }
  480.  
  481.         /// <summary>
  482.         /// This callback function will be called immediately after the Direct3D device has 
  483.         /// been destroyed, which generally happens as a result of application termination or 
  484.         /// windowed/full screen toggles. Resources created in the OnCreateDevice callback 
  485.         /// should be released here, which generally includes all Pool.Managed resources. 
  486.         /// </summary>
  487.         private void OnDestroyDevice(object sender, EventArgs e)
  488.         {
  489.             if(skybox != null)
  490.                 for(int i = 0; i < NumberSkyBoxes; ++i )
  491.                 {
  492.                     if(skybox[i] != null)
  493.                         skybox[i].OnDestroyDevice();
  494.                 }
  495.  
  496.             if(prtMesh != null)
  497.                 prtMesh.OnDestroyDevice();
  498.  
  499.             DirectionWidget.OnDestroyDevice();
  500.  
  501.             if(Simulator != null)
  502.                 Simulator.Stop();
  503.         }
  504.  
  505.         /// <summary>
  506.         /// This callback function will be called once at the beginning of every frame. This is the
  507.         /// best location for your application to handle updates to the scene, but is not 
  508.         /// intended to contain actual rendering calls, which should instead be placed in the 
  509.         /// OnFrameRender callback.  
  510.         /// </summary>
  511.         public void OnFrameMove(Device device, double appTime, float elapsedTime)
  512.         {
  513.             // Update the camera's position based on user input 
  514.             camera.FrameMove(elapsedTime);
  515.         }
  516.  
  517.         private void RenderStartup(Device device, double appTime, float elapsedTime)
  518.         {
  519.             bool beginSceneCalled = false;
  520.  
  521.             // Clear the render target and the zbuffer 
  522.             device.Clear(ClearFlags.ZBuffer | ClearFlags.Target, ClearColor1 , 1.0f, 0);
  523.  
  524.             // Render the scene
  525.             try
  526.             {
  527.                 device.BeginScene();
  528.                 beginSceneCalled = true;
  529.  
  530.                 RenderText();
  531.                 if( IsRenderUI )
  532.                 {
  533.                     hud.OnRender( elapsedTime );
  534.                     startUpUI.OnRender( elapsedTime );
  535.                     startUpUI2.OnRender( elapsedTime );
  536.                 }
  537.             }
  538.             finally
  539.             {
  540.                 if (beginSceneCalled)
  541.                     device.EndScene();
  542.             }
  543.         }
  544.  
  545.         /// <summary>
  546.         /// Load a mesh and optionally generate the PRT results file if they aren't already cached
  547.         /// </summary>
  548.         void LoadSceneAndOptGenResults( Device device, string meshFileName, string resultsFileName,
  549.             int numberRays, int numberBounces, bool isSubSurface )
  550.         {
  551.             string meshFileLongName = Utility.FindMediaFile(meshFileName);
  552.  
  553.             try
  554.             {
  555.                 string resultsFileLongName = Utility.FindMediaFile(resultsFileName);
  556.             }
  557.             catch(MediaNotFoundException)
  558.             {
  559.                 SimulatorOptions options = new SimulatorOptions();
  560.  
  561.                 options.InputMesh = meshFileName;
  562.                 
  563.                 options.InitialDir = System.IO.Path.GetDirectoryName(Utility.FindMediaFile(options.InputMesh));
  564.                 options.ResultsFileName = System.IO.Path.GetFileName(resultsFileName);
  565.                 options.Order = 6;
  566.                 options.NumberRays = numberRays;
  567.                 options.NumberBounces = numberBounces;
  568.                 options.IsSubsurfaceScattering = isSubSurface;
  569.                 options.LengthScale = 25.0f;
  570.                 options.NumberChannels = 3;
  571.  
  572.                 options.PredefinedMaterialIndex = 0;
  573.                 options.RelativeIndexOfRefraction = 1.3f;
  574.                 options.Diffuse = White;
  575.                 options.Absorption = new ColorValue( 0.0030f, 0.0030f, 0.0460f, 1.0f );
  576.                 options.ReducedScattering = new ColorValue( 2.00f, 2.00f, 2.00f, 1.0f );
  577.  
  578.                 options.IsAdaptive = false;
  579.                 options.IsRobustMeshRefine = true;
  580.                 options.RobustMeshRefineMinEdgeLength = 0.0f;
  581.                 options.RobustMeshRefineMaxSubdiv = 2;
  582.                 options.IsAdaptiveDL = true;
  583.                 options.AdaptiveDLMinEdgeLength = 0.03f;
  584.                 options.AdaptiveDLThreshold = 8e-5f;
  585.                 options.AdaptiveDLMaxSubdiv = 3;
  586.                 options.IsAdaptiveBounce = false;
  587.                 options.AdaptiveBounceMinEdgeLength = 0.03f;
  588.                 options.AdaptiveBounceThreshold = 8e-5f;
  589.                 options.AdaptiveBounceMaxSubdiv = 3;
  590.                 options.OutputMesh = "shapes1_adaptive.x";
  591.                 options.IsBinaryOutputXFile = true;
  592.  
  593.                 options.IsSaveCompressedResults = true;
  594.                 options.Quality = CompressionQuality.SlowHighQuality;
  595.                 options.NumberPcaVectors = 24;
  596.                 options.NumberClusters = 1;
  597.  
  598.                 prtMesh.LoadMesh( device, meshFileName );
  599.  
  600.                 SetRadii();
  601.  
  602.                 Simulator.Run( device, options, prtMesh );
  603.                 applicationState = ApplicationState.SimulatorRunning;
  604.  
  605.                 return;
  606.             }
  607.             LoadScene( device, meshFileName, resultsFileName);
  608.         }
  609.  
  610.         private void LoadScene(Device device, string meshFileName, string resultsFileName )
  611.         {
  612.             string meshFileLongName = Utility.FindMediaFile(meshFileName);
  613.             string resultsFileLongName = Utility.FindMediaFile(resultsFileName);
  614.  
  615.             prtMesh.LoadMesh(device, meshFileName);
  616.  
  617.             // Setup the camera's view parameters
  618.             Vector3 eyePt = new Vector3(0.0f, 0.0f, -5.0f);
  619.             Vector3 lookAtPt = new Vector3(0.0f, 0.0f, -0.0f);
  620.             camera.Reset();
  621.             camera.SetViewQuat( new Quaternion(0.0f, 0.0f, 0.0f, 1.0f) );
  622.             camera.SetWorldQuat( new Quaternion(0.0f, 0.0f, 0.0f, 1.0f) );
  623.             camera.SetViewParameters( eyePt, lookAtPt );
  624.             // Update camera's viewing radius
  625.             currentObjectRadius = prtMesh.Radius;
  626.             camera.SetRadius( currentObjectRadius * 3.0f, currentObjectRadius * 0.1f, currentObjectRadius * 20.0f );
  627.             camera.SetModelCenter( prtMesh.Center );
  628.  
  629.  
  630.             bool loadCompressed = false;
  631.             if(resultsFileLongName.EndsWith(".pca"))
  632.                 loadCompressed = true;
  633.  
  634.             if( loadCompressed )
  635.             {
  636.                 prtMesh.LoadCompPrtBufferFromFile( resultsFileLongName );
  637.             }
  638.             else
  639.             {
  640.                 prtMesh.LoadPrtBufferFromFile( resultsFileLongName );
  641.                 prtMesh.CompressBuffer(CompressionQuality.FastLowQuality, 1, 24);
  642.             }
  643.  
  644.             prtMesh.ExtractCompressedDataForPrtShader();
  645.             prtMesh.LoadEffects( device, SampleFramework.DeviceCaps);
  646.  
  647.             applicationState = ApplicationState.RenderScene;
  648.             Dialog.SetRefreshTime((float)FrameworkTimer.GetTime()); 
  649.             IsRenderCompressionUI = false;
  650.         }
  651.  
  652.         void ResetUI()
  653.         {
  654.             renderingUI.GetComboBox(EnvironmentA).SetSelectedByData( 0 );
  655.             renderingUI.GetComboBox(EnvironmentB).SetSelectedByData( 2 );
  656.             renderingUI.GetSlider(EnvironmentOne).Value = 50; 
  657.             renderingUI.GetSlider(EnvironmentTwo).Value = 50; 
  658.             renderingUI.GetSlider(EnvironmentBlend).Value = 0;
  659.  
  660.             renderingUI2.GetCheckbox( RenderUI).IsChecked = true;
  661.             renderingUI2.GetCheckbox( RenderMap).IsChecked = true;
  662.             IsRenderEnvMap = true;
  663.             renderingUI2.GetCheckbox( RenderArrows).IsChecked = true;
  664.             renderingUI2.GetCheckbox( RenderMesh).IsChecked = true;
  665.             renderingUI2.GetCheckbox( RenderTexture).IsChecked = true;
  666.             renderingUI2.GetCheckbox( WireFrame ).IsChecked = false;
  667.             renderingUI2.GetCheckbox( SHProjection).IsChecked = false;
  668.  
  669.             renderingUI2.GetSlider( LightScale ).SetRange( 0, 200 );
  670.             renderingUI2.GetSlider( LightScale ).Value = 0;
  671.             renderingUI2.GetSlider( NumberLights).Value = 1;
  672.  
  673.             string str = string.Format("# Lights: {0}", renderingUI2.GetSlider( NumberLights).Value );
  674.             renderingUI2.GetStaticText( NumberLightsStatic).SetText( str );
  675.             numberActiveLights = renderingUI2.GetSlider( NumberLights).Value;
  676.             activeLight %= numberActiveLights;
  677.  
  678.             renderingUI2.GetSlider( LightAngle).Value = 45;
  679.             int lightAngle = renderingUI2.GetSlider( LightAngle).Value;
  680.             str = string.Format("Cone Angle: {0}", lightAngle );
  681.             renderingUI2.GetStaticText( LightAngleStatic).SetText( str );
  682.  
  683.             renderingUI3.GetRadioButton( TechniqueNDotL).SetChecked( false, true );
  684.             renderingUI3.GetRadioButton( TechniqueSHIrrad).SetChecked( false, true );
  685.             renderingUI3.GetRadioButton( TechniquePrt).SetChecked( true, true );
  686.         }
  687.  
  688.         private void UpdateLightingEnvironment()
  689.         {
  690.             float env1 = renderingUI.GetSlider( EnvironmentOne ).Value / 100.0f;
  691.             float env2 = renderingUI.GetSlider( EnvironmentTwo ).Value / 100.0f;
  692.             float envBlend = renderingUI.GetSlider( EnvironmentBlend ).Value / 100.0f;
  693.             float lightScale = renderingUI2.GetSlider( LightScale ).Value * 0.01f;
  694.             float coneRadius = (float) Math.PI * renderingUI2.GetSlider( LightAngle ).Value / 180.0f;
  695.  
  696.             float[,][] light = new float[MaximumLights, 3][];
  697.             for(int i = 0; i < MaximumLights; i++)
  698.                 for(int j = 0; j < 3; j++)
  699.                     light[i,j] = new float[SphericalHarmonics.MaximumOrder * SphericalHarmonics.MaximumOrder];
  700.  
  701.             // Calculate light scale color
  702.             ColorValue lightColor = ColorOperator.Scale(PrtPerVertex.White, lightScale);
  703.  
  704.             int order = prtMesh.Order;
  705.  
  706.             // Pass in the light direction, the intensity of each channel, and it returns
  707.             // the source radiance as an array of order^2 SH coefficients for each color channel.  
  708.             Vector3 lightDirObjectSpace;
  709.             Matrix worldInv;
  710.             worldInv = Matrix.Invert(camera.WorldMatrix);
  711.  
  712.             for( int i = 0; i < numberActiveLights; i++ )
  713.             {
  714.                 // Transform the world space light dir into object space
  715.                 // Note that if there's multiple objects using Prt in the scene, then
  716.                 // for each object you need to either evaulate the lights in object space
  717.                 // evaulate the lights in world and rotate the light coefficients 
  718.                 // into object space.
  719.                 lightDirObjectSpace = Vector3.TransformNormal(lightControl[i].LightDirection, worldInv);
  720.  
  721.                 // This sample uses SphericalHarmonics.EvaluateDirectionalLight(), but there's other 
  722.                 // types of lights provided by SphericalHarmonics.Evaluate*.  Pass in the 
  723.                 // order of SH, color of the light, and the direction of the light 
  724.                 // in object space.
  725.                 // The output is the source radiance coefficients for the SH basis functions.  
  726.                 // There are 3 outputs, one for each channel (R,G,B). 
  727.                 // Each output is an array of order^2 floats.
  728.                 SphericalHarmonics.EvaluateConeLight(order, lightDirObjectSpace, coneRadius, 
  729.                     lightColor.Red, lightColor.Green, lightColor.Blue, light[i,0], light[i,1], light[i,2]);
  730.             }
  731.  
  732.             float[][] sum = new float[3][];
  733.             for(int i = 0; i < 3; i++)
  734.                 sum[i] = new float[SphericalHarmonics.MaximumOrder * SphericalHarmonics.MaximumOrder];
  735.  
  736.             // For multiple lights, just them sum up using SphericalHarmonics.Add()
  737.             for( int i = 0; i < numberActiveLights; i++ )
  738.             {
  739.                 // SphericalHarmonics.Add() will add order^2 floats.  There are 3 color channels, 
  740.                 // so call it 3 times.
  741.                 SphericalHarmonics.Add( sum[0], order, sum[0], light[i, 0] );
  742.                 SphericalHarmonics.Add( sum[1], order, sum[1], light[i, 1] );
  743.                 SphericalHarmonics.Add( sum[2], order, sum[2], light[i, 2] );
  744.             }
  745.  
  746.             float[][] skybox1 = new float[3][];
  747.             for( int i = 0; i < 3; i++)
  748.                 skybox1[i] = new float[SphericalHarmonics.MaximumOrder * SphericalHarmonics.MaximumOrder];
  749.  
  750.             float[][] skybox1Rot = new float[3][];
  751.             for( int i = 0; i < 3; i++)
  752.                 skybox1Rot[i] = new float[SphericalHarmonics.MaximumOrder * SphericalHarmonics.MaximumOrder];
  753.  
  754.             SphericalHarmonics.Scale( skybox1[0], order, skyboxLightSH[skyboxA, 0], env1 * (1.0f - envBlend) );
  755.             SphericalHarmonics.Scale( skybox1[1], order, skyboxLightSH[skyboxA, 1], env1 * (1.0f - envBlend) );
  756.             SphericalHarmonics.Scale( skybox1[2], order, skyboxLightSH[skyboxA, 2], env1 * (1.0f - envBlend) );
  757.             SphericalHarmonics.Rotate( skybox1Rot[0], order, worldInv, skybox1[0] );
  758.             SphericalHarmonics.Rotate( skybox1Rot[1], order, worldInv, skybox1[1] );
  759.             SphericalHarmonics.Rotate( skybox1Rot[2], order, worldInv, skybox1[2] );
  760.             SphericalHarmonics.Add( sum[0], order, sum[0], skybox1Rot[0] );
  761.             SphericalHarmonics.Add( sum[1], order, sum[1], skybox1Rot[1] );
  762.             SphericalHarmonics.Add( sum[2], order, sum[2], skybox1Rot[2] );
  763.  
  764.             float[][] skybox2 = new float[3][];
  765.             for( int i = 0; i < 3; i++)
  766.                 skybox2[i] = new float[SphericalHarmonics.MaximumOrder * SphericalHarmonics.MaximumOrder];
  767.  
  768.             float[][] skybox2Rot = new float[3][];
  769.             for( int i = 0; i < 3; i++)
  770.                 skybox2Rot[i] = new float[SphericalHarmonics.MaximumOrder * SphericalHarmonics.MaximumOrder];
  771.  
  772.             SphericalHarmonics.Scale( skybox2[0], order, skyboxLightSH[skyboxB, 0], env2 * envBlend );
  773.             SphericalHarmonics.Scale( skybox2[1], order, skyboxLightSH[skyboxB, 1], env2 * envBlend );
  774.             SphericalHarmonics.Scale( skybox2[2], order, skyboxLightSH[skyboxB, 2], env2 * envBlend );
  775.             SphericalHarmonics.Rotate( skybox2Rot[0], order, worldInv, skybox2[0] );
  776.             SphericalHarmonics.Rotate( skybox2Rot[1], order, worldInv, skybox2[1] );
  777.             SphericalHarmonics.Rotate( skybox2Rot[2], order, worldInv, skybox2[2] );
  778.             SphericalHarmonics.Add( sum[0], order, sum[0], skybox2Rot[0] );
  779.             SphericalHarmonics.Add( sum[1], order, sum[1], skybox2Rot[1] );
  780.             SphericalHarmonics.Add( sum[2], order, sum[2], skybox2Rot[2] );
  781.  
  782.             prtMesh.ComputeShaderConstants( sum[0], sum[1], sum[2], order * order );
  783.             prtMesh.ComputeSHIrradEnvMapConstants( sum[0], sum[1], sum[2] );
  784.         }
  785.  
  786.         private void RenderSimulatorRunning(Device device, double appTime, float elapsedTime)
  787.         {
  788.             bool beginSceneCalled = false;
  789.  
  790.             // Clear the render target and the zbuffer 
  791.             device.Clear(ClearFlags.ZBuffer | ClearFlags.Target, ClearColor1 , 1.0f, 0);
  792.  
  793.             // Render the scene
  794.             try
  795.             {
  796.                 device.BeginScene();
  797.                 beginSceneCalled = true;
  798.  
  799.                 RenderText();
  800.                 simulatorRunningUI.OnRender( elapsedTime );
  801.             }
  802.             finally
  803.             {
  804.                 if (beginSceneCalled)
  805.                     device.EndScene();
  806.             }
  807.         }
  808.  
  809.         //--------------------------------------------------------------------------------------
  810.         private void RenderPrt(Device device, double appTime, float elapsedTime)
  811.         {
  812.             bool beginSceneCalled = false;
  813.  
  814.             device.SetRenderState(RenderStates.FillMode, (int)(IsWireframe? FillMode.WireFrame : FillMode.Solid));
  815.  
  816.             // Clear the render target and the zbuffer 
  817.             device.Clear(ClearFlags.ZBuffer | ClearFlags.Target, Color.Black , 1.0f, 0);
  818.  
  819.             // Render the scene
  820.             try
  821.             {
  822.                 device.BeginScene();
  823.                 beginSceneCalled = true;
  824.                 
  825.                 Matrix worldMatrix = camera.WorldMatrix;
  826.                 Matrix viewMatrix = camera.ViewMatrix;
  827.                 Matrix projectionMatrix = camera.ProjectionMatrix;
  828.                 Matrix worldViewProjection = worldMatrix * viewMatrix * projectionMatrix;
  829.  
  830.                 if( IsRenderEnvMap && !IsWireframe )
  831.                 {
  832.                     float env1 = renderingUI.GetSlider( EnvironmentOne ).Value / 100.0f;
  833.                     float env2 = renderingUI.GetSlider( EnvironmentTwo ).Value / 100.0f;
  834.                     float envBlend = renderingUI.GetSlider( EnvironmentBlend ).Value / 100.0f;
  835.  
  836.                     device.SetRenderState( RenderStates.AlphaBlendEnable, true );
  837.                     device.SetRenderState( RenderStates.SourceBlend, (int) Blend.SourceAlpha );
  838.                     device.SetRenderState( RenderStates.DestinationBlend, (int) Blend.One);
  839.  
  840.                     skybox[skyboxA].DrawSH = IsRenderSHProjection;
  841.                     skybox[skyboxB].DrawSH = IsRenderSHProjection;
  842.  
  843.                     Matrix viewProjection = viewMatrix * projectionMatrix;
  844.                     skybox[skyboxA].Render( viewProjection, (1.0f - envBlend), env1 );
  845.                     skybox[skyboxB].Render( viewProjection, (envBlend), env2 );
  846.  
  847.                     device.SetRenderState( RenderStates.AlphaBlendEnable, false );
  848.                 }
  849.  
  850.                 float lightScale = renderingUI2.GetSlider( LightScale ).Value * 0.01f;
  851.                 if( IsRenderArrows && lightScale > 0.0f )
  852.                 {
  853.                     // Render the light spheres so the user can visually see the light direction
  854.                     for( int i = 0; i < numberActiveLights; i++ )
  855.                     {
  856.                         ColorValue arrowColor = ( i == activeLight ) ? Yellow : White;
  857.                         lightControl[i].OnRender( arrowColor, viewMatrix, projectionMatrix, camera.EyeLocation);
  858.                     }
  859.                 }
  860.  
  861.                 if( IsRenderMesh )
  862.                 {
  863.                     switch( technique )
  864.                     {
  865.                         case 0: // Prt
  866.                             prtMesh.RenderWithPrt( device, worldViewProjection, IsRenderWithAlbedoTexture );
  867.                             break;
  868.  
  869.                         case 1: // SHIrradEnvMap
  870.                             prtMesh.RenderWithSHIrradEnvMap( device, worldViewProjection, IsRenderWithAlbedoTexture );
  871.                             break;
  872.  
  873.                         case 2: // N dot L
  874.                         {
  875.                             Matrix worldInv = Matrix.Invert(camera.WorldMatrix);
  876.                             prtMesh.RenderWithNDotL( device, worldViewProjection, worldInv, IsRenderWithAlbedoTexture, lightControl, numberActiveLights, lightScale );
  877.                             break;
  878.                         }
  879.                     }
  880.                 }
  881.                 RenderText();
  882.                 if( IsRenderUI )
  883.                 {
  884.                     hud.OnRender( elapsedTime );
  885.                     renderingUI.OnRender(elapsedTime);
  886.                     renderingUI2.OnRender(elapsedTime);
  887.                     renderingUI3.OnRender(elapsedTime);
  888.                     if( IsRenderCompressionUI )
  889.                         compressionUI.OnRender(elapsedTime);
  890.                 }
  891.             }
  892.             finally
  893.             {
  894.                 if (beginSceneCalled)
  895.                     device.EndScene();
  896.             }
  897.         }
  898.  
  899.         /// <summary>
  900.         /// This callback function will be called at the end of every frame to perform all the 
  901.         /// rendering calls for the scene, and it will also be called if the window needs to be 
  902.         /// repainted. After this function has returned, the sample framework will call 
  903.         /// Device.Present to display the contents of the next buffer in the swap chain
  904.         /// </summary>
  905.         public void OnFrameRender(Device device, double appTime, float elapsedTime)
  906.         {
  907.             switch( applicationState )
  908.             {
  909.                 case ApplicationState.Startup: 
  910.                     RenderStartup( device, appTime, elapsedTime ); 
  911.                     break;
  912.  
  913.                 case ApplicationState.SimulatorOptions:
  914.                 {
  915.                     SampleFramework.Pause(false, true);
  916.                     PrtOptionsForm dlg = new PrtOptionsForm();
  917.                     RetryDialog:
  918.                     System.Windows.Forms.DialogResult result = dlg.ShowDialog();
  919.                     if( result == System.Windows.Forms.DialogResult.OK )
  920.                     {                
  921.                         SimulatorOptions options = dlg.GetOptions();
  922.                         prtMesh.LoadMesh( device, options.InputMesh );
  923.  
  924.                         SetRadii();
  925.  
  926.                         Simulator.Run( device, options, prtMesh );
  927.                         applicationState = ApplicationState.SimulatorRunning;
  928.                     }
  929.                     else if (result == System.Windows.Forms.DialogResult.Retry)
  930.                     {
  931.                         goto RetryDialog;
  932.                     }
  933.                     else
  934.                     {
  935.                         applicationState = ApplicationState.Startup; 
  936.                     }
  937.                     SampleFramework.Pause(false, false);
  938.                     break;
  939.                 }
  940.  
  941.                 case ApplicationState.SimulatorRunning:
  942.                 {
  943.                     string str;
  944.                     if( Simulator.PercentComplete >= 0.0f )
  945.                         str = String.Format("Step {0} of {1}: {2:f1}% done", Simulator.CurrentPass, Simulator.NumPasses, Simulator.PercentComplete );
  946.                     else
  947.                         str = String.Format("Step {0} of {1} (progress n/a)", Simulator.CurrentPass, Simulator.NumPasses );
  948.                     simulatorRunningUI.GetStaticText( SimulatorStatus ).SetText( str );
  949.                     simulatorRunningUI.GetStaticText( SimulatorStatus2 ).SetText( Simulator.CurrentPassName );
  950.  
  951.                     RenderSimulatorRunning( device, appTime, elapsedTime );
  952.                     System.Threading.Thread.Sleep(50); // Yield time to simulator thread
  953.  
  954.                     if( !Simulator.IsRunning )
  955.                     {
  956.                         prtMesh.LoadEffects( device, SampleFramework.DeviceCaps);
  957.                         applicationState = ApplicationState.RenderScene;
  958.                         Dialog.SetRefreshTime((float)FrameworkTimer.GetTime()); 
  959.                         IsRenderCompressionUI = false;
  960.                     }
  961.                     RenderSimulatorRunning( device, appTime, elapsedTime );
  962.                     break;
  963.                 }
  964.                    
  965.                 case ApplicationState.LoadPrtBuffer:
  966.                 {
  967.                     PrtLoadForm dlg = new PrtLoadForm();
  968.                     if( dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK )
  969.                     {
  970.                         SimulatorOptions options = dlg.GetOptions();
  971.                         if( !options.IsAdaptive)
  972.                             LoadScene( device, options.InputMesh, options.ResultsFileName );
  973.                         else
  974.                             LoadScene( device, options.OutputMesh, options.ResultsFileName );
  975.                     }
  976.                     else
  977.                     {
  978.                         applicationState = ApplicationState.Startup;
  979.                     }
  980.                     break;
  981.                 }
  982.  
  983.                 case ApplicationState.RenderScene: 
  984.                     UpdateLightingEnvironment();
  985.                     RenderPrt( device, appTime, elapsedTime ); 
  986.                     break;
  987.             
  988.                 default:
  989.                     System.Diagnostics.Debug.Assert(false);
  990.                     break;
  991.             }
  992. //          abra = false;
  993.         }
  994.  
  995.         /// <summary>
  996.         /// Render the help and statistics text. This function uses the Font object for 
  997.         /// efficient text rendering.
  998.         /// </summary>
  999.         private void RenderText()
  1000.         {
  1001.             if(!IsRenderText) return;
  1002.  
  1003.             // The helper object simply helps keep track of text position, and color
  1004.             // and then it calls textFont.DrawText(textSprite, text, rect, DrawTextFormat.NoClip, color);
  1005.             // If null is passed in as the sprite object, then it will work however the 
  1006.             // textFont.DrawText() will not be batched together.  Batching calls improves performance.
  1007.             TextHelper txtHelper = new TextHelper(statsFont, textSprite, 15);
  1008.  
  1009.             // Output statistics
  1010.             txtHelper.Begin();
  1011.             txtHelper.SetInsertionPoint(5,5);
  1012.             txtHelper.SetForegroundColor(Color.Yellow);
  1013.             txtHelper.DrawTextLine(SampleFramework.FrameStats);
  1014.             txtHelper.DrawTextLine(SampleFramework.DeviceStats);
  1015.  
  1016.             if(!IsRenderUI)
  1017.                 txtHelper.DrawTextLine("Press '4' to show UI");
  1018.  
  1019.             txtHelper.End();
  1020.         }
  1021.  
  1022.         /// <summary>
  1023.         /// As a convenience, the sample framework inspects the incoming windows messages for
  1024.         /// keystroke messages and decodes the message parameters to pass relevant keyboard
  1025.         /// messages to the application.  The framework does not remove the underlying keystroke 
  1026.         /// messages, which are still passed to the application's MsgProc callback.
  1027.         /// </summary>
  1028.         private void OnKeyEvent(System.Windows.Forms.Keys key, bool isKeyDown, bool isKeyUp)
  1029.         {
  1030.             if (isKeyDown)
  1031.             {
  1032.                 switch(key)
  1033.                 {
  1034.                     // Demo hotkeys
  1035.                     case System.Windows.Forms.Keys.Z: 
  1036.                     {
  1037.                         LoadSceneAndOptGenResults( SampleFramework.Device, "PRT Demo\\cube_on_plane.x", 
  1038.                                 "PRT Demo\\cube_on_plane_1k_6b_prtresults.pca", 1024, 6, false ); 
  1039.  
  1040.                         renderingUI.IsUsingNonUserEvents = true;
  1041.                         renderingUI2.IsUsingNonUserEvents = true;
  1042.                         renderingUI3.IsUsingNonUserEvents = true;
  1043.                         ResetUI();
  1044.                         renderingUI2.GetCheckbox( RenderTexture ).IsChecked = false;
  1045.                         renderingUI.IsUsingNonUserEvents = false;
  1046.                         renderingUI2.IsUsingNonUserEvents = false;
  1047.                         renderingUI3.IsUsingNonUserEvents = false;
  1048.                         break;
  1049.                     }
  1050.  
  1051.                     case System.Windows.Forms.Keys.X: 
  1052.                     {
  1053.                         LoadSceneAndOptGenResults( SampleFramework.Device, "PRT Demo\\LandShark.x", 
  1054.                                 "PRT Demo\\02_LandShark_1k_prtresults.pca", 1024, 1, false ); 
  1055.  
  1056.                         renderingUI.IsUsingNonUserEvents = false;
  1057.                         renderingUI2.IsUsingNonUserEvents = false;
  1058.                         renderingUI3.IsUsingNonUserEvents = false;
  1059.                         ResetUI();
  1060.                         renderingUI.IsUsingNonUserEvents = false;
  1061.                         renderingUI2.IsUsingNonUserEvents = false;
  1062.                         renderingUI3.IsUsingNonUserEvents = false;
  1063.                         break;
  1064.                     }
  1065.  
  1066.                     case System.Windows.Forms.Keys.C: 
  1067.                     {
  1068.                         LoadSceneAndOptGenResults( SampleFramework.Device, "PRT Demo\\wall_with_pillars.x", 
  1069.                             "PRT Demo\\wall_with_pillars_1k_prtresults.pca", 1024, 1, false ); 
  1070.  
  1071.                         renderingUI.IsUsingNonUserEvents = true;
  1072.                         renderingUI2.IsUsingNonUserEvents = true;
  1073.                         renderingUI3.IsUsingNonUserEvents = true;
  1074.                         ResetUI();
  1075.                         renderingUI.IsUsingNonUserEvents = false;
  1076.                         renderingUI2.IsUsingNonUserEvents = false;
  1077.                         renderingUI3.IsUsingNonUserEvents = false;
  1078.                         break;
  1079.                     }
  1080.  
  1081.                     case System.Windows.Forms.Keys.V: 
  1082.                     {
  1083.                         LoadSceneAndOptGenResults( SampleFramework.Device, "PRT Demo\\Head_Sad.x", 
  1084.                             "PRT Demo\\Head_Sad_1k_prtresults.pca", 1024, 1, false ); 
  1085.  
  1086.                         renderingUI.IsUsingNonUserEvents = true;
  1087.                         renderingUI2.IsUsingNonUserEvents = true;
  1088.                         renderingUI3.IsUsingNonUserEvents = true;
  1089.                         ResetUI();
  1090.                         renderingUI.IsUsingNonUserEvents = false;
  1091.                         renderingUI2.IsUsingNonUserEvents = false;
  1092.                         renderingUI3.IsUsingNonUserEvents = false;
  1093.                         break;
  1094.                     }
  1095.  
  1096.                     case System.Windows.Forms.Keys.B: 
  1097.                     {
  1098.                         LoadSceneAndOptGenResults( SampleFramework.Device, "PRT Demo\\Head_Big_Ears.x", 
  1099.                             "PRT Demo\\Head_Big_Ears_1k_subsurf_prtresults.pca", 1024, 1, true ); 
  1100.  
  1101.                         renderingUI.IsUsingNonUserEvents = true;
  1102.                         renderingUI2.IsUsingNonUserEvents = true;
  1103.                         renderingUI3.IsUsingNonUserEvents = true;
  1104.                         ResetUI();
  1105.                         renderingUI.GetSlider(EnvironmentOne).Value = 0; 
  1106.                         renderingUI.GetSlider(EnvironmentTwo).Value = 0;
  1107.                         renderingUI2.GetSlider( LightScale).SetRange( 0, 1000 );
  1108.                         renderingUI2.GetSlider( LightScale).Value = 200;
  1109.                         renderingUI.IsUsingNonUserEvents = false;
  1110.                         renderingUI2.IsUsingNonUserEvents = false;
  1111.                         renderingUI3.IsUsingNonUserEvents = false;
  1112.                         break;
  1113.                     }
  1114.  
  1115.                     case System.Windows.Forms.Keys.F1: isHelpShowing = !isHelpShowing; break;
  1116.                     case System.Windows.Forms.Keys.F8:
  1117.                     case System.Windows.Forms.Keys.W: IsWireframe = !IsWireframe; renderingUI2.GetCheckbox( WireFrame).IsChecked = IsWireframe; break;
  1118.                 }
  1119.             }
  1120.         }
  1121.  
  1122.         /// <summary>
  1123.         /// Before handling window messages, the sample framework passes incoming windows 
  1124.         /// messages to the application through this callback function. If the application sets 
  1125.         /// noFurtherProcessing to true, the sample framework will not process the message
  1126.         /// </summary>
  1127.         public IntPtr OnMsgProc(IntPtr hWnd, NativeMethods.WindowMessage msg, IntPtr wParam, IntPtr lParam, ref bool noFurtherProcessing)
  1128.         {
  1129.             if( msg == NativeMethods.WindowMessage.KeyDown && wParam.ToInt32() == (Int32) System.Windows.Forms.Keys.F8 )
  1130.                 noFurtherProcessing = true;
  1131.  
  1132.             // Give the dialog a chance to handle the message first
  1133.             noFurtherProcessing = hud.MessageProc(hWnd, msg, wParam, lParam);
  1134.             if (noFurtherProcessing)
  1135.                 return IntPtr.Zero;
  1136.  
  1137.             switch( applicationState)
  1138.             {
  1139.                 case ApplicationState.Startup:
  1140.                     // Give the dialog a chance to handle the message first
  1141.                     noFurtherProcessing = startUpUI.MessageProc(hWnd, msg, wParam, lParam);
  1142.                     if (noFurtherProcessing)
  1143.                         return IntPtr.Zero;
  1144.  
  1145.                     // Give the dialog a chance to handle the message first
  1146.                     noFurtherProcessing = startUpUI2.MessageProc(hWnd, msg, wParam, lParam);
  1147.                     if (noFurtherProcessing)
  1148.                         return IntPtr.Zero;
  1149.  
  1150.                     break;
  1151.  
  1152.                 case ApplicationState.SimulatorRunning:
  1153.                     // Give the dialog a chance to handle the message first
  1154.                     noFurtherProcessing = simulatorRunningUI.MessageProc(hWnd, msg, wParam, lParam);
  1155.                     if (noFurtherProcessing)
  1156.                         return IntPtr.Zero;
  1157.  
  1158.                     break;
  1159.  
  1160.                 case ApplicationState.RenderScene:
  1161.                     if(IsRenderUI || msg == NativeMethods.WindowMessage.KeyDown || msg == NativeMethods.WindowMessage.KeyUp)
  1162.                     {
  1163.                         // Give the dialog a chance to handle the message first
  1164.                         noFurtherProcessing = renderingUI.MessageProc(hWnd, msg, wParam, lParam);
  1165.                         if (noFurtherProcessing)
  1166.                             return IntPtr.Zero;
  1167.  
  1168.                         // Give the dialog a chance to handle the message first
  1169.                         noFurtherProcessing = renderingUI2.MessageProc(hWnd, msg, wParam, lParam);
  1170.                         if (noFurtherProcessing)
  1171.                             return IntPtr.Zero;
  1172.  
  1173.                         // Give the dialog a chance to handle the message first
  1174.                         noFurtherProcessing = renderingUI3.MessageProc(hWnd, msg, wParam, lParam);
  1175.                         if (noFurtherProcessing)
  1176.                             return IntPtr.Zero;
  1177.  
  1178.                         if(IsRenderCompressionUI)
  1179.                         {
  1180.                             // Give the dialog a chance to handle the message first
  1181.                             noFurtherProcessing = compressionUI.MessageProc(hWnd, msg, wParam, lParam);
  1182.                             if (noFurtherProcessing)
  1183.                                 return IntPtr.Zero;
  1184.                         }
  1185.                     }
  1186.  
  1187.                     lightControl[activeLight].HandleMessages( hWnd, msg, wParam, lParam );
  1188.  
  1189.                     // Pass all remaining windows messages to camera so it can respond to user input
  1190.                     camera.HandleMessages(hWnd, msg, wParam, lParam);
  1191.  
  1192.                     break;
  1193.  
  1194.                 default:
  1195.                     break;
  1196.             }
  1197.  
  1198.             return IntPtr.Zero;
  1199.         }
  1200.  
  1201.         /// <summary>
  1202.         /// Initializes the application
  1203.         /// </summary>
  1204.         public void InitializeApplication()
  1205.         {
  1206.             for(int i = 0; i < MaximumLights; i++)
  1207.             {
  1208.                 lightControl[i] = new DirectionWidget();
  1209.                 lightControl[i].LightDirection = new Vector3( (float) Math.Sin(Math.PI * 2 * i / MaximumLights - Math.PI / 6),
  1210.                     0, -(float)Math.Cos(Math.PI * 2 * i / MaximumLights - Math.PI / 6)) ;
  1211.                 lightControl[i].RotateButtonMask = MouseButtonMask.Middle;
  1212.             }
  1213.  
  1214.             activeLight = 0;
  1215.             numberActiveLights = 1;
  1216.  
  1217.             int y = 10;
  1218.             // Initialize the HUD
  1219.             Button fullScreenButton = hud.AddButton(ToggleFullscreen,"Toggle full screen", 35, y, 125,22);
  1220.             Button toggleRefButton = hud.AddButton(ToggleReference,"Toggle reference (F3)", 35, y += 24, 125,22);
  1221.             Button changeDeviceButton = hud.AddButton(ChangeDevice,"Change Device (F2)", 35, y += 24, 125,22);
  1222.             // Hook the button events for when these items are clicked
  1223.             fullScreenButton.Click += new EventHandler(OnFullscreenClicked);
  1224.             toggleRefButton.Click += new EventHandler(OnRefClicked);
  1225.             changeDeviceButton.Click += new EventHandler(OnChangeDeviceClicked);
  1226.  
  1227.             // Now add the sample specific UI
  1228.  
  1229.             // Title font for comboboxes
  1230.             startUpUI.SetFont( 1, "Arial", 24, FontWeight.Bold );
  1231.             Element element = startUpUI.GetDefaultElement( ControlType.StaticText, 0 );
  1232.             element.FontIndex = 1;
  1233.             element.textFormat = DrawTextFormat.Center | DrawTextFormat.Bottom;
  1234.  
  1235.             y = 10; 
  1236.             // Initialize startUpUI
  1237.             startUpUI.AddStatic( -1, "What would you like to do?", 0, 10, 300, 22 );
  1238.             Button simulatorButton      = startUpUI.AddButton(SimulatorInt32, "Run Prt simulator", 90, 42, 125, 40 );
  1239.             Button loadPrtBufferButton  = startUpUI.AddButton(LoadPrtBuffer, "View saved results", 90, 84, 125, 40 );
  1240.             // Hook the button events for when these items are clicked
  1241.             simulatorButton.Click       += new EventHandler(OnSimulatorClicked);
  1242.             loadPrtBufferButton.Click   += new EventHandler(OnLoadPrtClicked);
  1243.  
  1244.             y = 10; 
  1245.             // Initialize startUpUI2
  1246.             Button scene1Button = startUpUI2.AddButton(Scene1, "Demo Scene 1 (Z)", 0, y += 24, 125, 22);
  1247.             Button scene2Button = startUpUI2.AddButton(Scene2, "Demo Scene 2 (X)", 0, y += 24, 125, 22);
  1248.             Button scene3Button = startUpUI2.AddButton(Scene3, "Demo Scene 3 (C)", 0, y += 24, 125, 22);
  1249.             Button scene4Button = startUpUI2.AddButton(Scene4, "Demo Scene 4 (V)", 0, y += 24, 125, 22);
  1250.             Button scene5Button = startUpUI2.AddButton(Scene5, "Demo Scene 5 (B)", 0, y += 24, 125, 22);
  1251.             // Hook the button events for when these items are clicked
  1252.             scene1Button.Click += new EventHandler(OnScene1Clicked);
  1253.             scene2Button.Click += new EventHandler(OnScene2Clicked);
  1254.             scene3Button.Click += new EventHandler(OnScene3Clicked);
  1255.             scene4Button.Click += new EventHandler(OnScene4Clicked);
  1256.             scene5Button.Click += new EventHandler(OnScene5Clicked);
  1257.  
  1258.             // Title font for simulatorRunningUI
  1259.             simulatorRunningUI.SetFont( 1, "Arial", 24, FontWeight.Bold );
  1260.             element = simulatorRunningUI.GetDefaultElement( ControlType.StaticText, 0 );
  1261.             element.FontIndex = 1;
  1262.             element.textFormat = DrawTextFormat.Center | DrawTextFormat.Bottom;
  1263.  
  1264.             y = 10; 
  1265.             // Initialize simulatorRunningUI
  1266.             simulatorRunningUI.AddStatic( SimulatorStatus, String.Empty, 0, 0, 600, 22 );
  1267.             simulatorRunningUI.AddStatic( SimulatorStatus2, String.Empty, 0, 30, 600, 22 );
  1268.             Button stopSimulatorButton = simulatorRunningUI.AddButton( StopSimulator, "Stop Prt simulator", 240, 60, 125, 40 );
  1269.             // Hook the button events for when these items are clicked
  1270.             stopSimulatorButton.Click += new EventHandler(OnStopSimulatorClicked);
  1271.  
  1272.             // Title font for renderingUI2
  1273.             renderingUI2.SetFont( 1, "Arial", 14, FontWeight.Bold );
  1274.             element = renderingUI2.GetDefaultElement( ControlType.StaticText, 0 );
  1275.             element.FontIndex = 1;
  1276.             element.textFormat = DrawTextFormat.Left | DrawTextFormat.Bottom;
  1277.  
  1278.             y = 10; 
  1279.             // Initialize renderingUI2
  1280.             Checkbox renderUICB = renderingUI2.AddCheckBox( RenderUI, "Show UI (4)", 35, y += 24, 125, 22, IsRenderUI, System.Windows.Forms.Keys.D4, true);
  1281.             Checkbox renderMapCB = renderingUI2.AddCheckBox( RenderMap, "Background (5)", 35, y += 24, 125, 22, IsRenderEnvMap, System.Windows.Forms.Keys.D5, true);
  1282.             Checkbox renderArrowsCB = renderingUI2.AddCheckBox( RenderArrows, "Arrows (6)", 35, y += 24, 125, 22, IsRenderArrows, System.Windows.Forms.Keys.D6, true);  
  1283.             Checkbox renderMeshCB = renderingUI2.AddCheckBox( RenderMesh, "Mesh (7)", 35, y += 24, 125, 22, IsRenderMesh, System.Windows.Forms.Keys.D7, true);   
  1284.             Checkbox renderTextureCB = renderingUI2.AddCheckBox( RenderTexture, "Texture (8)", 35, y += 24, 125, 22, IsRenderWithAlbedoTexture, System.Windows.Forms.Keys.D8, true);   
  1285.             Checkbox renderWireFrameCB = renderingUI2.AddCheckBox( WireFrame, "Wireframe (W)", 35, y += 24, 125, 22, IsWireframe ); 
  1286.             Checkbox renderSHProjectionCB = renderingUI2.AddCheckBox( SHProjection, "SH Projection (H)", 35, y += 24, 125, 22, IsRenderSHProjection, System.Windows.Forms.Keys.H, true);   
  1287.             // Add the event handlers
  1288.             renderUICB.Changed += new EventHandler(OnRenderUICBChanged);
  1289.             renderMapCB.Changed += new EventHandler(OnRenderMapCBChanged);
  1290.             renderArrowsCB.Changed += new EventHandler(OnRenderArrowsCBChanged);
  1291.             renderMeshCB.Changed += new EventHandler(OnRenderMeshCBChanged);
  1292.             renderTextureCB.Changed += new EventHandler(OnRenderTextureCBChanged);
  1293.             renderWireFrameCB.Changed += new EventHandler(OnRenderWireFrameCBChanged);
  1294.             renderSHProjectionCB.Changed += new EventHandler(OnRenderSHProjectionCBChanged);
  1295.             
  1296.             string str;
  1297.  
  1298.             y += 10;
  1299.             
  1300.             // Initialize renderingUI2 more
  1301.             str = String.Format("Light scale: {0:f2}", 0.0f );
  1302.             renderingUI2.AddStatic( LightScaleStatic, str, 35, y += 24, 125, 22 );
  1303.             Slider lightScaleSlider = renderingUI2.AddSlider( LightScale, 50, y += 24, 100, 22, 0, 200, (int)(lightScaleForPrt * 100.0f), true);
  1304.             // Add the event handler
  1305.             lightScaleSlider.ValueChanged += new EventHandler(OnLightScaleSliderChanged);
  1306.  
  1307.             str = String.Format("# Lights: {0}", numberActiveLights);
  1308.             renderingUI2.AddStatic( NumberLightsStatic, str, 35, y += 24, 125, 22 );
  1309.             Slider numberLightsSlider = renderingUI2.AddSlider( NumberLights, 50, y += 24, 100, 22, 1, MaximumLights, numberActiveLights, true );
  1310.             // Add the event handler
  1311.             numberLightsSlider.ValueChanged += new EventHandler(OnNumLightsSliderChanged);
  1312.  
  1313.             str = String.Format("Cone Angle: 45");
  1314.             renderingUI2.AddStatic( LightAngleStatic, str, 35, y += 24, 125, 22 );
  1315.             Slider lightAngleSlider = renderingUI2.AddSlider( LightAngle, 50, y += 24, 100, 22, 1, 180, 45, true);
  1316.             // Add the event handler
  1317.             lightAngleSlider.ValueChanged += new EventHandler(OnLightAngleSliderChanged);
  1318.  
  1319.             y += 5;
  1320.             Button activeLightButton = renderingUI2.AddButton( ActiveLight, "Change active light (K)", 35, y += 24, 125, 22, System.Windows.Forms.Keys.K, true );
  1321.  
  1322.             y += 5;
  1323.             Button compressionButton = renderingUI2.AddButton( Compression, "Compression Settings", 35, y += 24, 125, 22 );
  1324.  
  1325.             y += 5;
  1326.             Button restartButton = renderingUI2.AddButton( Restart, "Restart", 35, y += 24, 125, 22 );
  1327.  
  1328.             // Add the event handlers
  1329.             activeLightButton.Click += new EventHandler(OnActiveLightButtonClicked);
  1330.             compressionButton.Click += new EventHandler(OnCompressionButtonClicked);
  1331.             restartButton.Click += new EventHandler(OnRestartButtonClicked);
  1332.  
  1333.             bool isEnable = lightScaleSlider.Value != 0;
  1334.             lightAngleSlider.IsEnabled = isEnable;
  1335.             numberLightsSlider.IsEnabled = isEnable;
  1336.             renderingUI2.GetStaticText(LightAngleStatic).IsEnabled = isEnable;
  1337.             renderingUI2.GetStaticText(NumberLightsStatic).IsEnabled = isEnable;
  1338.             activeLightButton.IsEnabled = isEnable;
  1339.  
  1340.             // Title font for renderingUI3
  1341.             renderingUI3.SetFont( 1, "Arial", 14, FontWeight.Bold);
  1342.             element = renderingUI3.GetDefaultElement( ControlType.StaticText, 0 );
  1343.             element.FontIndex = 1;
  1344.             element.textFormat = DrawTextFormat.Left | DrawTextFormat.Bottom;
  1345.  
  1346.             y = 0; 
  1347.             // Initialize renderingUI3
  1348.             renderingUI3.AddStatic( Static, "(T)echnique", 0, y, 150, 25 );
  1349.             RadioButton techniquePrt        = renderingUI3.AddRadioButton( TechniquePrt     , 1, "(1) PRT"          , 0, y += 24, 150, 22, true, System.Windows.Forms.Keys.D1, true );
  1350.             RadioButton techniqueSHIrradRB  = renderingUI3.AddRadioButton( TechniqueSHIrrad , 1, "(2) SHIrradEnvMap", 0, y += 24, 150, 22, false, System.Windows.Forms.Keys.D2, true );
  1351.             RadioButton techniqueNDotLRB    = renderingUI3.AddRadioButton( TechniqueNDotL   , 1, "(3) N dot L"      , 0, y += 24, 150, 22, false, System.Windows.Forms.Keys.D3, true );
  1352.             // Add the event handlers
  1353.             techniquePrt.Changed += new EventHandler(OnTechniquePrtChanged);
  1354.             techniqueSHIrradRB.Changed += new EventHandler(OnTechniqueSHIrradRBChanged); 
  1355.             techniqueNDotLRB.Changed += new EventHandler(OnTechniqueNDotLRBChanged);
  1356.  
  1357.             // Title font for renderingUI
  1358.             renderingUI.SetFont( 1, "Arial", 14, FontWeight.Bold);
  1359.             element = renderingUI.GetDefaultElement( ControlType.StaticText, 0 );
  1360.             element.FontIndex = 1;
  1361.             element.textFormat = DrawTextFormat.Left | DrawTextFormat.Bottom;
  1362.  
  1363.             int startY = 0;
  1364.             int x = 10;
  1365.             y = startY; 
  1366.             renderingUI.AddStatic( Static, "(F)irst Light Probe", x, y += 24, 150, 25 );
  1367.             ComboBox environmentACB = renderingUI.AddComboBox( EnvironmentA, x, y += 24, 150, 22, System.Windows.Forms.Keys.F, true );   
  1368.             environmentACB.SetDropHeight( 30 );
  1369.  
  1370.             environmentACB.AddItem( "Eucalyptus Grove", 0 );
  1371.             if(NumberSkyBoxes > 1)
  1372.                 environmentACB.AddItem( "The Uffizi Gallery", 1 );
  1373.             if(NumberSkyBoxes > 2)
  1374.                 environmentACB.AddItem( "Galileo's Tomb", 2 );
  1375.             if(NumberSkyBoxes > 3)
  1376.                 environmentACB.AddItem( "Grace Cathedral", 3 );
  1377.             if(NumberSkyBoxes > 4)
  1378.                 environmentACB.AddItem( "St. Peter's Basilica", 4 );
  1379.  
  1380.             environmentACB.SetSelectedByData( skyboxA );
  1381.             // Add the event handler
  1382.             environmentACB.Changed += new EventHandler(OnEnvironmentACBChanged);
  1383.  
  1384.             renderingUI.AddStatic( Static, "First Light Probe Scaler", x, y += 24, 150, 25 );
  1385.             Slider environmentOneSlider = renderingUI.AddSlider( EnvironmentOne, x, y += 24, 150, 22, 0, 100, 50, true );
  1386.  
  1387.             x += 175;
  1388.             y = startY + 30; 
  1389.             renderingUI.AddStatic( Static, "Light Probe Blend", x, y += 24, 100, 25 );
  1390.             Slider environmentBlendSlider = renderingUI.AddSlider( EnvironmentBlend, x, y += 24, 100, 22, 0, 100, 0, true );   
  1391.  
  1392.             x += 125;
  1393.             y = startY; 
  1394.             renderingUI.AddStatic( Static, "(S)econd Light Probe", x, y += 24, 150, 25 );
  1395.             ComboBox environmentBCB = renderingUI.AddComboBox( EnvironmentB, x, y += 24, 150, 22, System.Windows.Forms.Keys.S, true );
  1396.             environmentBCB.SetDropHeight( 30 );
  1397.  
  1398.             environmentBCB.AddItem( "Eucalyptus Grove", 0 );
  1399.             if(NumberSkyBoxes > 1)
  1400.                 environmentBCB.AddItem( "The Uffizi Gallery", 1 );
  1401.             if(NumberSkyBoxes > 2)
  1402.                 environmentBCB.AddItem( "Galileo's Tomb", 2 );
  1403.             if(NumberSkyBoxes > 3)
  1404.                 environmentBCB.AddItem( "Grace Cathedral", 3 );
  1405.             if(NumberSkyBoxes > 4)
  1406.                 environmentBCB.AddItem( "St. Peter's Basilica", 4 );
  1407.  
  1408.             environmentBCB.SetSelectedByData( skyboxB );
  1409.             // Add the event handler
  1410.             environmentBCB.Changed += new EventHandler(OnEnvironmentBCBChanged);
  1411.  
  1412.             renderingUI.AddStatic( Static, "Second Light Probe Scaler", x, y += 24, 150, 25 );
  1413.             Slider environmentTwoSlider = renderingUI.AddSlider( EnvironmentTwo, x, y += 24, 150, 22, 0, 100, 50, true );
  1414.  
  1415.             y = 10;
  1416.  
  1417.             SimulatorOptions options = PrtOptions.GlobalOptions;
  1418.  
  1419.             // CompressionUI
  1420.             compressionUI.AddStatic( NumberPcaVectors, "Number of Pca Vectors: 24", 30, y += 24, 120, 22 );
  1421.             Slider numberPcaSlider = compressionUI.AddSlider( NumberPcaVectors, 30, y += 24, 120, 22, 1, 6, options.NumberPcaVectors / 4, true );
  1422.             numberPcaSlider.ValueChanged += new EventHandler(OnNumberPcaSliderValueChanged);
  1423.  
  1424.             compressionUI.AddStatic( NumberClusters, "Number of Clusters: 1", 30, y += 24, 120, 22 );
  1425.             Slider numberClustersSlider = compressionUI.AddSlider( NumberClusters, 30, y += 24, 120, 22, 1, 40, options.NumberClusters, true );
  1426.             numberClustersSlider.ValueChanged += new EventHandler(OnNumberClustersSliderValueChanged);
  1427.  
  1428.             compressionUI.AddStatic( MaximumConstants, "Maximum VS Constants: 0", 30, y += 24, 120, 22 );
  1429.             compressionUI.AddStatic( CurrentConstantsStatic, "Current VS Constants:", 30, y += 24, 120, 22 );
  1430.             compressionUI.AddStatic( CurrentConstants, "0", -10, y += 12, 250, 22 );
  1431.             Button applyButton = compressionUI.AddButton( Apply, "Apply", 30, y += 24, 120, 24 );
  1432.             applyButton.Click += new EventHandler(OnApplyButtonClicked);
  1433.  
  1434.             str = string.Format("Number of Pca: {0}", options.NumberPcaVectors );
  1435.             compressionUI.GetStaticText( NumberPcaVectors ).SetText( str );
  1436.             str = string.Format("Number of Clusters: {0}", options.NumberClusters );
  1437.             compressionUI.GetStaticText( NumberClusters ).SetText( str );           
  1438.             UpdateConstText();
  1439.         }
  1440.  
  1441.         /// <summary>
  1442.         /// update the dlg's text & controls
  1443.         /// </summary>
  1444.         private void UpdateConstText()
  1445.         {
  1446.             int numberClusters = compressionUI.GetSlider( NumberClusters ).Value;
  1447.             int numberPcaVectors        = compressionUI.GetSlider( NumberPcaVectors ).Value * 4;
  1448.             int maximumVertexShaderConst = SampleFramework.DeviceCaps.MaxVertexShaderConst;
  1449.             int numberVConsts   = numberClusters * (1 + 3 * numberPcaVectors / 4) + 4;
  1450.             string str = string.Format("{0} * (1 + (3 * {1} / 4)) + 4 = {2}", numberClusters, numberPcaVectors, numberVConsts );
  1451.             compressionUI.GetStaticText( CurrentConstantsStatic ).SetText(str);
  1452.  
  1453.             bool isEnable = numberVConsts < maximumVertexShaderConst;
  1454.             compressionUI.GetButton( Apply ).IsEnabled = isEnable;
  1455.         }
  1456.  
  1457.  
  1458.         #region Event Handler Routines
  1459.  
  1460.         /* hud */
  1461.         /// <summary>Called when the change device button is clicked</summary>
  1462.         private void OnChangeDeviceClicked(object sender, EventArgs e)
  1463.         {
  1464.             SampleFramework.ShowSettingsDialog(!SampleFramework.IsD3DSettingsDialogShowing);
  1465.         }
  1466.  
  1467.         /// <summary>Called when the full screen button is clicked</summary>
  1468.         private void OnFullscreenClicked(object sender, EventArgs e)
  1469.         {
  1470.             SampleFramework.ToggleFullscreen();
  1471.         }
  1472.  
  1473.         /// <summary>Called when the ref button is clicked</summary>
  1474.         private void OnRefClicked(object sender, EventArgs e)
  1475.         {
  1476.             SampleFramework.ToggleReference();
  1477.         }
  1478.  
  1479.         /* startUpUI */
  1480.         /// <summary>Called when the Run Prt simulator button is clicked</summary>
  1481.         private void OnSimulatorClicked(object sender, EventArgs e)
  1482.         {
  1483.             applicationState = ApplicationState.SimulatorOptions;
  1484.         }
  1485.  
  1486.         /// <summary>Called when the View saved results button is clicked</summary>
  1487.         private void OnLoadPrtClicked(object sender, EventArgs e)
  1488.         {
  1489.             applicationState = ApplicationState.LoadPrtBuffer;
  1490.         }
  1491.  
  1492.         /* startUpUI2 */
  1493.         /// <summary>Called when the Demo Scene 1 button is clicked</summary>
  1494.         private void OnScene1Clicked(object sender, EventArgs e)
  1495.         {
  1496.             OnKeyEvent(System.Windows.Forms.Keys.Z, true, false);
  1497.         }
  1498.  
  1499.         /// <summary>Called when the Demo Scene 2 button is clicked</summary>
  1500.         private void OnScene2Clicked(object sender, EventArgs e)
  1501.         {
  1502.             OnKeyEvent(System.Windows.Forms.Keys.X, true, false);
  1503.         }
  1504.  
  1505.         /// <summary>Called when the Demo Scene 3 button is clicked</summary>
  1506.         private void OnScene3Clicked(object sender, EventArgs e)
  1507.         {
  1508.             OnKeyEvent(System.Windows.Forms.Keys.C, true, false);
  1509.         }
  1510.  
  1511.         /// <summary>Called when the Demo Scene 4 button is clicked</summary>
  1512.         private void OnScene4Clicked(object sender, EventArgs e)
  1513.         {
  1514.             OnKeyEvent(System.Windows.Forms.Keys.V, true, false);
  1515.         }
  1516.  
  1517.         /// <summary>Called when the Demo Scene 5 button is clicked</summary>
  1518.         private void OnScene5Clicked(object sender, EventArgs e)
  1519.         {
  1520.             OnKeyEvent(System.Windows.Forms.Keys.B, true, false);
  1521.         }
  1522.  
  1523.         /* simulatorRunningUI */
  1524.         /// <summary>Called when the Stop Prt simulator button is clicked</summary>
  1525.         private void OnStopSimulatorClicked(object sender, EventArgs e)
  1526.         {
  1527.             Simulator.Stop();
  1528.             applicationState = ApplicationState.Startup;
  1529.         }
  1530.  
  1531.         /* renderingUI2 */
  1532.         /// <summary>Called when the Show UI button is clicked</summary>
  1533.         private void OnRenderUICBChanged(object sender, EventArgs e)
  1534.         {
  1535.             IsRenderUI = renderingUI2.GetCheckbox( RenderUI ).IsChecked;
  1536.         }
  1537.  
  1538.         /// <summary>Called when the Background button is clicked</summary>
  1539.         private void OnRenderMapCBChanged(object sender, EventArgs e)
  1540.         {
  1541.             IsRenderEnvMap = renderingUI2.GetCheckbox( RenderMap ).IsChecked;
  1542.         }
  1543.  
  1544.         /// <summary>Called when the Arrows button is clicked</summary>
  1545.         private void OnRenderArrowsCBChanged(object sender, EventArgs e)
  1546.         {
  1547.             IsRenderArrows = renderingUI2.GetCheckbox( RenderArrows ).IsChecked;
  1548.         }
  1549.  
  1550.         /// <summary>Called when the Mesh button is clicked</summary>
  1551.         private void OnRenderMeshCBChanged(object sender, EventArgs e)
  1552.         {
  1553.             IsRenderMesh = renderingUI2.GetCheckbox( RenderMesh ).IsChecked;
  1554.         }
  1555.  
  1556.         /// <summary>Called when the Texture button is clicked</summary>
  1557.         private void OnRenderTextureCBChanged(object sender, EventArgs e)
  1558.         {
  1559.             IsRenderWithAlbedoTexture = renderingUI2.GetCheckbox( RenderTexture ).IsChecked;
  1560.         }
  1561.  
  1562.         /// <summary>Called when the Wireframe button is clicked</summary>
  1563.         private void OnRenderWireFrameCBChanged(object sender, EventArgs e)
  1564.         {
  1565.             IsWireframe = renderingUI2.GetCheckbox( WireFrame ).IsChecked;
  1566.         }
  1567.  
  1568.         /// <summary>Called when the SH Projection button is clicked</summary>
  1569.         private void OnRenderSHProjectionCBChanged(object sender, EventArgs e)
  1570.         {
  1571.             IsRenderSHProjection = renderingUI2.GetCheckbox( SHProjection ).IsChecked;
  1572.         }
  1573.  
  1574.         /// <summary>Called when the Light scale Slider is changed</summary>
  1575.         private void OnLightScaleSliderChanged(object sender, EventArgs e)
  1576.         {
  1577.             float lightScale = (float) (renderingUI2.GetSlider( LightScale ).Value * 0.01f);
  1578.             string str = string.Format("Light scale: {0:f2}", lightScale );
  1579.             renderingUI2.GetStaticText( LightScaleStatic ).SetText( str );
  1580.  
  1581.             bool isEnable = (renderingUI2.GetSlider( LightScale ).Value != 0 );
  1582.             renderingUI2.GetSlider( LightAngle ).IsEnabled = 
  1583.             renderingUI2.GetSlider( NumberLights ).IsEnabled = 
  1584.             renderingUI2.GetStaticText( LightAngleStatic ).IsEnabled = 
  1585.             renderingUI2.GetStaticText( NumberLightsStatic ).IsEnabled = 
  1586.             renderingUI2.GetButton( ActiveLight ).IsEnabled = isEnable;
  1587.         }
  1588.  
  1589.         /// <summary>Called when the # Lights Slider is changed</summary>
  1590.         private void OnNumLightsSliderChanged(object sender, EventArgs e)
  1591.         {
  1592.             if( !lightControl[ActiveLight].IsBeingDragged )
  1593.             {
  1594.                 string str = string.Format("# Lights: {0}", renderingUI2.GetSlider( NumberLights ).Value );
  1595.                 renderingUI2.GetStaticText( NumberLightsStatic ).SetText( str );
  1596.  
  1597.                 numberActiveLights = renderingUI2.GetSlider( NumberLights ).Value;
  1598.                 activeLight %= numberActiveLights;
  1599.             }
  1600.         }
  1601.  
  1602.         /// <summary>Called when the Cone Angle Slider is changed</summary>
  1603.         private void OnLightAngleSliderChanged(object sender, EventArgs e)
  1604.         {
  1605.             int lightAngle = renderingUI2.GetSlider( LightAngle ).Value;
  1606.             string str = string.Format("Cone Angle: {0}", lightAngle );
  1607.             renderingUI2.GetStaticText( LightAngleStatic ).SetText( str );
  1608.         }
  1609.         
  1610.         /// <summary>Called when the "Change active light (K)" button is clicked</summary>
  1611.         private void OnActiveLightButtonClicked(object sender, EventArgs e)
  1612.         {
  1613.             if( !lightControl[ActiveLight].IsBeingDragged )
  1614.             {
  1615.                 activeLight++;
  1616.                 activeLight %= numberActiveLights;
  1617.             }
  1618.         }
  1619.         
  1620.         /// <summary>Called when the "Compression Settings" button is clicked</summary>
  1621.         private void OnCompressionButtonClicked(object sender, EventArgs e)
  1622.         {
  1623.             if( prtMesh.IsUncompressedBufferLoaded )
  1624.             {
  1625.                 IsRenderCompressionUI = !IsRenderCompressionUI;
  1626.             }
  1627.             else
  1628.             {
  1629.                 System.Windows.Forms.MessageBox.Show(
  1630.                     "To change compression settings during rendering, please load an uncompressed buffer.  To make one use the simulator settings dialog to save an uncompressed buffer.",
  1631.                     "PRTPerVertex", 
  1632.                     System.Windows.Forms.MessageBoxButtons.OK);
  1633.             }
  1634.         }
  1635.  
  1636.         /// <summary>Called when the "Restart" button is clicked</summary>
  1637.         private void OnRestartButtonClicked(object sender, EventArgs e)
  1638.         {
  1639.             applicationState = ApplicationState.Startup;
  1640.         }
  1641.  
  1642.         /// <summary>Called when the "Number of Pca Vectors" Slider is changed</summary>
  1643.         private void OnNumberPcaSliderValueChanged(object sender, EventArgs e)
  1644.         {
  1645.             int numberPcaVectors = compressionUI.GetSlider( NumberPcaVectors ).Value * 4;
  1646.             string str = string.Format("Number of PCA: {0}", numberPcaVectors );
  1647.             compressionUI.GetStaticText( NumberPcaVectors ).SetText( str );           
  1648.  
  1649.             UpdateConstText();
  1650.         }
  1651.         
  1652.         /// <summary>Called when the "Number of Clusters" Slider is changed</summary>
  1653.         private void OnNumberClustersSliderValueChanged(object sender, EventArgs e)
  1654.         {
  1655.             int numberClusters = compressionUI.GetSlider( NumberClusters ).Value;
  1656.             string str = string.Format("Number of Clusters: {0}", numberClusters );
  1657.             compressionUI.GetStaticText( NumberClusters ).SetText( str );           
  1658.  
  1659.             UpdateConstText();
  1660.         }
  1661.         
  1662.         /// <summary>Called when the "(1) PRT" Radio Button is changed</summary>
  1663.         private void OnTechniquePrtChanged(object sender, EventArgs e)
  1664.         {
  1665.             float lightScale = (float) (renderingUI2.GetSlider( LightScale ).Value * 0.01f);
  1666.             switch( technique )
  1667.             { 
  1668.                 case 0: lightScaleForPrt = lightScale; break; 
  1669.                 case 1: lightScaleForSHIrrad = lightScale; break; 
  1670.                 case 2: lightScaleForNDotL = lightScale; break; 
  1671.             }
  1672.             technique = 0;
  1673.             renderingUI2.GetCheckbox( RenderMap ).IsChecked = true;
  1674.             IsRenderEnvMap = true;
  1675.             renderingUI2.IsUsingNonUserEvents = true;
  1676.             renderingUI2.GetSlider( LightScale ).Value = (int)(lightScaleForPrt * 100.0f);
  1677.             renderingUI2.IsUsingNonUserEvents = false;
  1678.         }
  1679.  
  1680.         /// <summary>Called when the "(2) SHIrradEnvMap" Radio Button is changed</summary>
  1681.         private void OnTechniqueSHIrradRBChanged(object sender, EventArgs e)
  1682.         {
  1683.             float lightScale = (float) (renderingUI2.GetSlider( LightScale ).Value * 0.01f);
  1684.             switch( technique )
  1685.             { 
  1686.                 case 0: lightScaleForPrt = lightScale; break; 
  1687.                 case 1: lightScaleForSHIrrad = lightScale; break; 
  1688.                 case 2: lightScaleForNDotL = lightScale; break; 
  1689.             }
  1690.             technique = 1;
  1691.             renderingUI2.GetCheckbox( RenderMap ).IsChecked = true;
  1692.             IsRenderEnvMap = true;
  1693.             renderingUI2.IsUsingNonUserEvents = true;
  1694.             renderingUI2.GetSlider( LightScale ).Value = (int)(lightScaleForSHIrrad * 100.0f);
  1695.             renderingUI2.IsUsingNonUserEvents = false;
  1696.         }
  1697.  
  1698.         /// <summary>Called when the "(3) N dot L" Radio Button is changed</summary>
  1699.         private void OnTechniqueNDotLRBChanged(object sender, EventArgs e)
  1700.         {
  1701.             float lightScale = (float) (renderingUI2.GetSlider( LightScale ).Value * 0.01f);
  1702.             switch( technique )
  1703.             { 
  1704.                 case 0: lightScaleForPrt = lightScale; break; 
  1705.                 case 1: lightScaleForSHIrrad = lightScale; break; 
  1706.                 case 2: lightScaleForNDotL = lightScale; break; 
  1707.             }
  1708.             technique = 2;
  1709.             renderingUI2.GetCheckbox( RenderMap ).IsChecked = false;
  1710.             IsRenderEnvMap = false;
  1711.             renderingUI2.IsUsingNonUserEvents = true;
  1712.             renderingUI2.GetSlider( LightScale ).Value = (int)(lightScaleForNDotL * 100.0f);
  1713.             renderingUI2.IsUsingNonUserEvents = false;
  1714.         }
  1715.  
  1716.         /// <summary>Called when the "(F)irst Light Probe" ComboBox is changed</summary>
  1717.         private void OnEnvironmentACBChanged(object sender, EventArgs e)
  1718.         {
  1719.             skyboxA = (int) renderingUI.GetComboBox( EnvironmentA ).GetSelectedData();
  1720.         }
  1721.  
  1722.         /// <summary>Called when the "(S)econd Light Probe" ComboBox is changed</summary>
  1723.         private void OnEnvironmentBCBChanged(object sender, EventArgs e)
  1724.         {
  1725.             skyboxB = (int) renderingUI.GetComboBox( EnvironmentB ).GetSelectedData();
  1726.         }
  1727.  
  1728.         /// <summary>Called when the "Apply" button is clicked</summary>
  1729.         private void OnApplyButtonClicked(object sender, EventArgs e)
  1730.         {
  1731.             int numberPcaVectors = compressionUI.GetSlider( NumberPcaVectors ).Value * 4;
  1732.             int numberClusters = compressionUI.GetSlider( NumberClusters ).Value;
  1733.  
  1734.             SimulatorOptions options = PrtOptions.GlobalOptions;
  1735.             options.NumberClusters = numberClusters;
  1736.             options.NumberPcaVectors = numberPcaVectors;
  1737.             PrtOptions.GlobalOptionsFile.SaveOptions(string.Empty);
  1738.  
  1739.             prtMesh.CompressBuffer( options.Quality, options.NumberClusters, options.NumberPcaVectors);
  1740.             prtMesh.ExtractCompressedDataForPrtShader();
  1741.             prtMesh.LoadEffects( SampleFramework.Device, SampleFramework.DeviceCaps);
  1742.         }
  1743.  
  1744.         #endregion
  1745.  
  1746.         /// <summary>
  1747.         /// Entry point to the program. Initializes everything and goes into a message processing 
  1748.         /// loop. Idle time is used to render the scene.
  1749.         /// </summary>
  1750.         static int Main()
  1751.         {
  1752.             using(Framework SampleFramework = new Framework())
  1753.             {
  1754.                 PrtPerVertex sample = new PrtPerVertex(SampleFramework);
  1755.                 // Set the callback functions. These functions allow the sample framework to notify
  1756.                 // the application about device changes, user input, and windows messages.  The 
  1757.                 // callbacks are optional so you need only set callbacks for events you're interested 
  1758.                 // in. However, if you don't handle the device reset/lost callbacks then the sample 
  1759.                 // framework won't be able to reset your device since the application must first 
  1760.                 // release all device resources before resetting.  Likewise, if you don't handle the 
  1761.                 // device created/destroyed callbacks then the sample framework won't be able to 
  1762.                 // recreate your device resources.
  1763.                 SampleFramework.Disposing += new EventHandler(sample.OnDestroyDevice);
  1764.                 SampleFramework.DeviceLost += new EventHandler(sample.OnLostDevice);
  1765.                 SampleFramework.DeviceCreated += new DeviceEventHandler(sample.OnCreateDevice);
  1766.                 SampleFramework.DeviceReset += new DeviceEventHandler(sample.OnResetDevice);
  1767.  
  1768.                 SampleFramework.SetKeyboardCallback(new KeyboardCallback(sample.OnKeyEvent));
  1769.                 SampleFramework.SetWndProcCallback(new WndProcCallback(sample.OnMsgProc));
  1770.  
  1771.                 SampleFramework.SetCallbackInterface(sample);
  1772.                 try
  1773.                 {
  1774.                     // Show the cursor and clip it when in full screen
  1775.                     SampleFramework.SetCursorSettings(true, true);
  1776.  
  1777.                     // Initialize
  1778.                     sample.InitializeApplication();
  1779.  
  1780.                     // Initialize the sample framework and create the desired window and Direct3D 
  1781.                     // device for the application. Calling each of these functions is optional, but they
  1782.                     // allow you to set several options which control the behavior of the SampleFramework.
  1783.                     SampleFramework.Initialize( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
  1784.                     //There is no way to do the override unless you parse command line parameters.
  1785.                     SampleFramework.CreateWindow("PrtPerVertex");
  1786.                     SampleFramework.CreateDevice( 0, true, 800, 600, sample);
  1787.                     Rectangle rectangle;
  1788.                     NativeMethods.GetWindowRect( SampleFramework.Window, out rectangle);
  1789.                     NativeMethods.SetWindowPos( SampleFramework.Window, (IntPtr) 0, rectangle.X, rectangle.Y, 808, 634, 0);
  1790.                     NativeMethods.GetWindowRect( SampleFramework.Window, out rectangle);
  1791.  
  1792.                     // Pass control to the sample framework for handling the message pump and 
  1793.                     // dispatching render calls. The sample framework will call your FrameMove 
  1794.                     // and FrameRender callback when there is idle time between handling window messages.
  1795.                     SampleFramework.MainLoop();
  1796.  
  1797.                 }
  1798. #if(DEBUG)
  1799.                 catch (Exception e)
  1800.                 {
  1801.                     // In debug mode show this error (maybe - depending on settings)
  1802.                     SampleFramework.DisplayErrorMessage(e);
  1803. #else
  1804.                 catch
  1805.                 {
  1806.                 // In release mode fail silently
  1807. #endif
  1808.                     // Ignore any exceptions here, they would have been handled by other areas
  1809.                     return (SampleFramework.ExitCode == 0) ? 1 : SampleFramework.ExitCode; // Return an error code here
  1810.                 }
  1811.  
  1812.                 // Perform any application-level cleanup here. Direct3D device resources are released within the
  1813.                 // appropriate callback functions and therefore don't require any cleanup code here.
  1814.                 return SampleFramework.ExitCode;
  1815.             }
  1816.         }
  1817.     }
  1818. }
  1819.